package com.devbobcorn.nekoration.blocks.entities;

import javax.annotation.Nullable;

import com.devbobcorn.nekoration.Nekoration;
import com.devbobcorn.nekoration.blocks.ItemDisplayBlock;
import com.devbobcorn.nekoration.network.ModPacketHandler;
import com.devbobcorn.nekoration.network.S2CUpdateCupboardData;

import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.inventory.container.ChestContainer;
import net.minecraft.inventory.container.Container;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
import net.minecraft.tileentity.ChestTileEntity;
import net.minecraft.tileentity.LockableLootTileEntity;
import net.minecraft.util.NonNullList;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.vector.Vector3i;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.fml.network.PacketDistributor;

public class ItemDisplayBlockEntity extends LockableLootTileEntity {
	private int openCount;
	private NonNullList<ItemStack> items;
    private final ItemStack airStack = new ItemStack(Items.AIR);
    public ItemStack[] renderItems = { airStack, airStack, airStack, airStack };

	public final boolean wallShelf;
	public final boolean playSound;

	public ItemDisplayBlockEntity() {
		super(ModTileEntityType.ITEM_DISPLAY_TYPE.get());
		this.items = NonNullList.withSize(27, ItemStack.EMPTY);
		this.wallShelf = false;
		this.playSound = true;
	}

	public ItemDisplayBlockEntity(boolean s, boolean p) {
		super(ModTileEntityType.ITEM_DISPLAY_TYPE.get());
		this.items = NonNullList.withSize(27, ItemStack.EMPTY);
		this.wallShelf = s;
		this.playSound = p;
	}

	public CompoundNBT save(CompoundNBT tag) {
		super.save(tag);
		if (!this.trySaveLootTable(tag)) {
			ItemStackHelper.saveAllItems(tag, this.items);
		}
		return tag;
	}

	public void load(BlockState state, CompoundNBT tag) {
		super.load(state, tag);
		this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
		if (!this.tryLoadLootTable(tag)) {
			ItemStackHelper.loadAllItems(tag, this.items);
		}
		// Init render items...
		int idx = 0;
		for (ItemStack item : this.items){
			if (!item.isEmpty()){
				renderItems[idx] = item.copy();
				idx++;
				if (idx >= 4)
					break;
			}
		}
	}

	@Nullable
	public SUpdateTileEntityPacket getUpdatePacket() {
		return new SUpdateTileEntityPacket(this.worldPosition, 2028, this.getUpdateTag());
	}

	public CompoundNBT getUpdateTag() {
		return this.save(new CompoundNBT());
	}

	public boolean onlyOpCanSetNbt() {
		return true;
	}

	@Nullable
	@Override
	public Container createMenu(int windowID, PlayerInventory playerInventory) {
		return ChestContainer.threeRows(windowID, playerInventory, this);
	}

	@Override
	public int getContainerSize() {
		return 27;
	}

	@Override
	protected NonNullList<ItemStack> getItems() {
		return items;
	}

	@Override
	protected void setItems(NonNullList<ItemStack> newItems) {
		items = newItems;
	}

	@Override
	protected ITextComponent getDefaultName() {
		return new TranslationTextComponent("block." + Nekoration.MODID + ".cupboard");
	}

	public void startOpen(PlayerEntity player) {
		if (!player.isSpectator()) {
			if (this.openCount < 0) {
				this.openCount = 0;
			}
			++this.openCount;
			BlockState blockstate = this.getBlockState();
			boolean flag = blockstate.getValue(ItemDisplayBlock.OPEN);
			if (!flag) {
				if (playSound)
					this.playSound(blockstate, SoundEvents.BARREL_OPEN);
				this.updateBlockState(blockstate, true);
			}
			this.scheduleRecheck();
		}

	}

	private void scheduleRecheck() {
		this.level.getBlockTicks().scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), 5);
	}

	public void recheckOpen() {
		int i = this.worldPosition.getX();
		int j = this.worldPosition.getY();
		int k = this.worldPosition.getZ();
		this.openCount = ChestTileEntity.getOpenCount(this.level, this, i, j, k);
		if (this.openCount > 0) {
			this.scheduleRecheck();
		} else {
			BlockState blockstate = this.getBlockState();
			if (!(blockstate.getBlock() instanceof ItemDisplayBlock)) {
				this.setRemoved();
				return;
			}
			boolean flag = blockstate.getValue(ItemDisplayBlock.OPEN);
			if (flag) {
				if (playSound)
					this.playSound(blockstate, SoundEvents.BARREL_CLOSE);
				this.updateBlockState(blockstate, false);
				ItemStack[] its = { airStack, airStack, airStack, airStack };
				// Find out the 4 items to display...
				int idx = 0;
				for (ItemStack item : ItemDisplayBlockEntity.this.items){
					if (!item.isEmpty()){
						its[idx] = item.copy();
						idx++;
						if (idx >= 4)
							break;
					}
				}
				// This called on SERVER SIDE...
				final S2CUpdateCupboardData packet = new S2CUpdateCupboardData(this.getBlockPos(), its);
				ModPacketHandler.CHANNEL.send(PacketDistributor.ALL.noArg(), packet);
			}
		}
	}

	public void stopOpen(PlayerEntity player) {
		if (!player.isSpectator()) {
		   --this.openCount;
		}
	}

	private void updateBlockState(BlockState state, boolean open) {
		this.level.setBlock(this.getBlockPos(), state.setValue(ItemDisplayBlock.OPEN, Boolean.valueOf(open)), 3);
	}

	private void playSound(BlockState state, SoundEvent sound) {
		Vector3i vector3i = state.getValue(ItemDisplayBlock.FACING).getNormal();
		double d0 = (double) this.worldPosition.getX() + 0.5D + (double) vector3i.getX() / 2.0D;
		double d1 = (double) this.worldPosition.getY() + 0.5D + (double) vector3i.getY() / 2.0D;
		double d2 = (double) this.worldPosition.getZ() + 0.5D + (double) vector3i.getZ() / 2.0D;
		this.level.playSound((PlayerEntity) null, d0, d1, d2, sound, SoundCategory.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F);
	}
}